package org.vic.strategy.duckDemo;

/**
 * 鸭子超类；
 * 每个鸭子都应该拥有  不同的名字，会游泳，可能会飞，可能会叫 的特性
 */
public abstract class Duck {
    // 将FlyBehavior、QuackBehavior的行为组合进来，无需关注具体的行为实现；
    // 提高代码的可扩展性，可变的部分交由行为接口进行扩展与修改
    // 如果需要增加新的行为，只需组合进来即可；
    FlyBehavior flyBehavior;
    QuackBehavior quackBehavior;

    // 为了让行为可以更加动态，更加人性化，我们可以通过setter方法来改变行为
    public void setFlyBehavior(FlyBehavior flyBehavior) {
        this.flyBehavior = flyBehavior;
    }
    public void setQuackBehavior(QuackBehavior quackBehavior) {
        this.quackBehavior = quackBehavior;
    }

    // 名字各不相同，由子类自行实现
    public abstract void myName();

    // 所有鸭子都会游泳！无需各自实现
    public void swim() {
        System.out.println("我是一只鸭，游啊游~");
    }

    /* +++++ / bad design +++++ */
    // 不是所有鸭子都会飞啊！
    // 如果所有鸭子都各自实现飞的东西，那么会飞的鸭子都重复写了飞翔的实现，不会飞的鸭子也重复写了不会飞翔的实现！！
    // bad!!!!! 这样存在太多的重复代码，重复工作了！！ 如何才能做到既可以区分会否飞翔的鸭子，又可以让代码可以复用呢？
    // ——> 组合的方式，将行为抽出来作为接口（has-a）
//    public abstract void fly();

    // 跟fly()一样存在同样的问题！
//    public abstract void quack();
    /* +++++ # bad design +++++ */

    /* +++++ / good design +++++ */
    public void performFly() {
        flyBehavior.fly();
    }

    public void performQuack() {
        quackBehavior.quack();
    }
    /* +++++ # good design +++++ */
}
